package com.ziq.zcamp.place

import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.amap.api.location.AMapLocation
import com.amap.api.maps.model.LatLng
import com.gmlive.camp.data.exception.LocalException
import com.permissionx.guolindev.PermissionX
import com.ziq.base.extension.launchWithTry
import com.ziq.base.extension.launchWithTryAsynchronous
import com.ziq.base.utils.permission.PermissionUtil
import com.ziq.zcamp.R
import com.ziq.zcamp.api.request.camp.CampListSearchParam
import com.ziq.zcamp.api.request.camp.CampNationNumListParam
import com.ziq.zcamp.api.request.camp.CampRankListParam
import com.ziq.zcamp.api.respond.camp.CampNationNumListRespond
import com.ziq.zcamp.api.service.CampService
import com.ziq.zcamp.api.service.NetWorkException
import com.ziq.zcamp.api.service.request
import com.ziq.zcamp.bean.place.AreaItem
import com.ziq.zcamp.bean.place.CampListItem
import com.ziq.zcamp.bean.place.CampNationNum
import com.ziq.zcamp.bean.search.SearchKeywordInfo
import com.ziq.zcamp.constant.PlaceSortType
import com.ziq.zcamp.manager.GlobalContextManager
import com.ziq.zcamp.util.MapUtil
import com.ziq.zcamp.util.encrypt.AesVr
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.withContext
import javax.inject.Inject

@HiltViewModel
class PlaceListFragmentViewModel @Inject constructor() : ViewModel(){

    @Inject
    lateinit var mCampService: CampService
    companion object {
        const val empty_id = -99
        const val UI_MODEL_LIST = "list"
        const val UI_MODEL_MAP = "map"
    }

    var uiModel:String = UI_MODEL_LIST

    var pageForFilter = 1
    var pageSize = 30

    var hasMoreForFilter = false


    val progressShow = MutableSharedFlow<Boolean>(replay = 0)
    val placeListRequestFinished = MutableSharedFlow<Boolean>(replay = 0)
    val errorShow = MutableLiveData<Boolean>()
    val placeListHasMore = MutableLiveData<Boolean>()
    val scrollToTop = MutableLiveData<Boolean>()

    val campRankList = MutableLiveData<List<CampListItem>?>()
    val nationNumList = MutableLiveData<List<CampNationNum>>()
    val placeList = MutableLiveData<List<CampListItem>>()

    var focusCampItem = MutableLiveData<CampListItem>()

    //搜索关键词
    val searchKeyword = MutableSharedFlow<SearchKeywordInfo>(replay = 0)

    private val encryptionUtils by lazy {
        AesVr()
    }

    var currentScreen : PlaceSortType = PlaceSortType.Distance // 默认 1距离优先，2人气优先，3好评优先
    var selectedItem = MutableLiveData<AreaItem>()

    var selectedCondition = MutableLiveData<MutableMap<Int, MutableList<Int>>>()
    var selectedConditionName = MutableLiveData<MutableMap<Int, MutableList<String>>>()




    //位置权限逻辑 -------------------start
    val locationGrantSharedFlow = MutableSharedFlow<Boolean>(replay = 0)
    var hasRequestPermission = false
    var hasGrantPermission = false
    var myLatLng: LatLng? = null //自身定位
    var updateForMyLatLng = MutableSharedFlow<AMapLocation?>(replay = 0)
    var currentLatLng: LatLng? = null //地图当前定位
    fun checkLocationPermissionForResume(activity: FragmentActivity){
        //之后进入的时候还没有获取到权限
        if(hasRequestPermission && !hasGrantPermission){
            checkPermissionStatus()
            //回来后获得了权限
            if(hasGrantPermission){
                getLocationPermission(activity)
            }
        }
        //第一次进入的时候
        if(!hasRequestPermission){
            getLocationPermission(activity)
        }
    }


    fun checkPermissionStatus(){
        var result = true
        for(item in PermissionUtil.locationPermission){
            if(!PermissionX.isGranted(GlobalContextManager.appContext!!, item)){
                result = false
            }
        }
        hasGrantPermission = result
    }

    fun getLocationPermission(activity: FragmentActivity){
        if(myLatLng != null){
            return
        }
        hasRequestPermission = true
        PermissionUtil.requestLocationPermission(activity, onGrant = {
            hasGrantPermission = true
            launchWithTry(whenTry = {
                locationGrantSharedFlow.emit(true)
            })
            resetMyLocation()
        }, onReject = {
            launchWithTry(whenTry = {
                locationGrantSharedFlow.emit(false)
            })
        }, onRemind = {
        })
    }

    var isReset = false
    fun resetMyLocation(){
        isReset = true
        MapUtil.getCurrentLocation(callback = {
            myLatLng = LatLng(it.latitude, it.longitude)
            launchWithTry(whenTry = {
                updateForMyLatLng.emit(it)
            })
        }, onFail = {
            launchWithTry(whenTry = {
                updateForMyLatLng.emit(null)
            })
        })
    }
    //位置权限逻辑 -------------------end

    //条件筛选
    fun addCondition(categoryId:Int?, categoryType: Int?, conditionId:Int?, conditionName:String?){
        if (categoryId != null && categoryType != null && conditionId != null){
            val map : MutableMap<Int, MutableList<Int>> =  selectedCondition.value?:mutableMapOf()
            if(map.containsKey(categoryId)){
                if(categoryType == 1){ // 单选
                    map[categoryId] = mutableListOf(conditionId)
                } else if(categoryType == 2){
                    map[categoryId]?.add(conditionId)
                }
            } else {
                map[categoryId] = mutableListOf(conditionId)
            }
            selectedCondition.postValue(map)
        }

        if (categoryId != null && categoryType != null && conditionName != null){
            val map : MutableMap<Int, MutableList<String>> =  selectedConditionName.value?:mutableMapOf()
            if(map.containsKey(categoryId)){
                if(categoryType == 1){ // 单选
                    map[categoryId] = mutableListOf(conditionName)
                } else if(categoryType == 2){
                    map[categoryId]?.add(conditionName)
                }
            } else {
                map[categoryId] = mutableListOf(conditionName)
            }
            selectedConditionName.postValue(map)
        }
    }
    fun removeCondition(categoryId:Int?){
        if (categoryId != null){
            val map : MutableMap<Int, MutableList<Int>> =  selectedCondition.value?:mutableMapOf()
            if(map.containsKey(categoryId)){
                map[categoryId]?.clear()
            }
            selectedCondition.postValue(map)
        }

        if (categoryId != null){
            val map : MutableMap<Int, MutableList<String>> =  selectedConditionName.value?:mutableMapOf()
            if(map.containsKey(categoryId)){
                map[categoryId]?.clear()
            }
            selectedConditionName.postValue(map)
        }
    }

    fun removeCondition(categoryId:Int?, categoryType: Int?, conditionId:Int?, conditionName:String?){
        if (categoryId != null && categoryType != null && conditionId != null){
            val map : MutableMap<Int, MutableList<Int>> =  selectedCondition.value?:mutableMapOf()
            if(map.containsKey(categoryId)){
                map[categoryId]?.remove(conditionId)
            }
            selectedCondition.postValue(map)
        }

        if (categoryId != null && categoryType != null && conditionName != null){
            val map : MutableMap<Int, MutableList<String>> =  selectedConditionName.value?:mutableMapOf()
            if(map.containsKey(categoryId)){
                map[categoryId]?.remove(conditionName)
            }
            selectedConditionName.postValue(map)
        }
    }

    fun getSelectedConditionList():MutableList<Int>{
        var list = mutableListOf<Int>()
        val map : MutableMap<Int, MutableList<Int>> =  selectedCondition.value?:mutableMapOf()
        for (items in map.values){
            list.addAll(items)
        }
        return list
    }

    var isFirstRefresh = true // 配合缓存显示
    fun onRefresh(showProgress: Boolean = false){
        launchWithTryAsynchronous(whenTry = {
            if(!isFirstRefresh){
                if(showProgress){
                    progressShow.emit(true)
                }
            }
            isFirstRefresh = false
            pageForFilter = 1
            hasMoreForFilter = false

            requestNationNumList()
            onRequestData()
        }, whenCatch = {
        })
    }

    fun onLoadMore(){
        onRequestData()
    }

    private fun onRequestData(){
        launchWithTryAsynchronous(whenTry = {
            placeListRequestFinished.emit(false)
            val needScrollToTop = pageForFilter == 1
            val adcode = selectedItem.value?.ad_code

            val tempPlaceList = mutableListOf<CampListItem>()
            if(pageForFilter != 1 && placeList.value != null){
                tempPlaceList.addAll(placeList.value!!)
            }

            if(pageForFilter == 1 || hasMoreForFilter){
                val respond = mCampService.campListSearch(CampListSearchParam().apply {
                    page = pageForFilter
                    page_size = pageSize
                    if (adcode?.isNotEmpty() == true) {
                        this.ad_code = adcode
                    }
                    latitude = "${myLatLng?.latitude}"
                    longitude = "${myLatLng?.longitude}"
                    this.list_sort_type = currentScreen.type
                    condition_list = getSelectedConditionList()
                }).request()

                if(respond.data?.list?.isNotEmpty() == true){
                    tempPlaceList.addAll(respond.data!!.list!!)
                }
                hasMoreForFilter = tempPlaceList.size < (respond.data?.total?:0)
                pageForFilter++
            }

            progressShow.emit(false)
            errorShow.postValue(false)
            placeListRequestFinished.emit(true)
            placeList.postValue(tempPlaceList)
            scrollToTop.postValue(needScrollToTop)
            placeListHasMore.postValue(hasMoreForFilter)

        }, whenCatch = {
            withContext(Dispatchers.Main){
                progressShow.emit(false)
                if(pageForFilter == 1){
                    errorShow.postValue(true)
                }
                placeListRequestFinished.emit(true)

                when(it){
                    is LocalException -> {
                        Toast.makeText(GlobalContextManager.appContext!!, GlobalContextManager.getString(R.string.all_net_error), Toast.LENGTH_SHORT).show()
                    }
                    is NetWorkException -> {
                        Toast.makeText(GlobalContextManager.appContext!!, it.message?:"", Toast.LENGTH_SHORT).show()
                    }
                    else -> {
                        Toast.makeText(GlobalContextManager.appContext!!, GlobalContextManager.getString(R.string.all_net_error), Toast.LENGTH_SHORT).show()
                    }
                }
            }
        })
    }

    fun requestRankData(provinces :List<AreaItem>?){
        launchWithTryAsynchronous(whenTry = {
            var ad_code = selectedItem.value?.ad_code
            if(provinces?.isNotEmpty() == true){
                for (province in provinces){
                    if(province.id == (selectedItem.value?.belong_id?:0L)){
                        ad_code = province.ad_code
                        break
                    }
                }
            }

            val respond = mCampService.campRankList(CampRankListParam().apply {
                page = 1
                page_size = 10
                if (ad_code?.isNotEmpty() == true) {
                    this.ad_code = ad_code
                }
                latitude = "${myLatLng?.latitude}"
                longitude = "${myLatLng?.longitude}"
            }).request()
            withContext(Dispatchers.Main){
                campRankList.value = respond?.data?.list
            }
        }, whenCatch = {
            it.printStackTrace()
        })
    }

    private fun requestNationNumList(
        onSuccess: ((result: CampNationNumListRespond) -> Unit)? = {
            if(it.data != null){
                nationNumList.postValue(it.data)
            }
        },
        onFail: ((result: String) -> Unit)? = {}) {
        launchWithTryAsynchronous(whenTry = {
            val respond = mCampService.campNationNumList(CampNationNumListParam().apply {
                condition_list = getSelectedConditionList()
            }).request()
            withContext(Dispatchers.Main){
                onSuccess?.invoke(respond!!)
            }
        }, whenCatch = {
            onFail?.invoke(it.message?:"")
            it.printStackTrace()
        })
    }

}